package com.example.excelimport.util;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.example.excelimport.entity.User;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Cell;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.File;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

@Component
@Slf4j
public class MillionDataGenerator {

    private static final String[] DEPARTMENTS = {"技术部", "销售部", "市场部", "人事部", "财务部"};
    private static final String[] NAMES = {"张三", "李四", "王五", "赵六", "钱七", "孙八", "周九", "吴十"};

    @Value("${file.upload-dir:./temp_files}")
    private String uploadDir;

    /**
     * 生成百万数据Excel文件
     */
    public String generateMillionData() {
        // 创建文件路径
        String fileName = "million_data_" + System.currentTimeMillis() + ".xlsx";
        String filePath = getFilePath(fileName);

        // 确保目录存在
        FileUtil.createFileDirectory(filePath);

        log.info("开始生成百万数据Excel文件: {}", filePath);
        long startTime = System.currentTimeMillis();

        try {
            // 正确的链式调用顺序：先配置write，再配置sheet
            ExcelWriter excelWriter = EasyExcel.write(filePath, User.class)
                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 在sheet之前配置
                    .build();

            try {
                WriteSheet writeSheet = EasyExcel.writerSheet("用户数据").build();

                // 分批生成数据，每批10万条
                int total = 1_000_000;
                int batchSize = 100_000;
                int batchCount = total / batchSize;

                for (int i = 0; i < batchCount; i++) {
                    List<User> batchData = generateBatchData(batchSize, i * batchSize);
                    excelWriter.write(batchData, writeSheet);
                    log.info("已生成第 {}/{} 批数据，共 {} 条", i + 1, batchCount, batchSize);
                }
            } finally {
                // 关闭writer
                if (excelWriter != null) {
                    excelWriter.finish();
                }
            }

            long endTime = System.currentTimeMillis();
            log.info("百万数据Excel生成完成，文件路径: {}，耗时: {} 秒",
                    filePath, (endTime - startTime) / 1000.0);

            return filePath;

        } catch (Exception e) {
            log.error("生成Excel文件失败", e);
            throw new RuntimeException("生成Excel文件失败", e);
        }
    }

    /**
     * 更简洁的写法 - 使用doWrite
     */
    public String generateMillionDataSimple() {
        String fileName = "million_data_" + System.currentTimeMillis() + ".xlsx";
        String filePath = getFilePath(fileName);

        FileUtil.createFileDirectory(filePath);

        log.info("开始生成百万数据Excel文件: {}", filePath);
        long startTime = System.currentTimeMillis();

        try {
            // 使用try-with-resources确保资源正确关闭
            try (ExcelWriter excelWriter = EasyExcel.write(filePath, User.class)
                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                    .build()) {

                WriteSheet writeSheet = EasyExcel.writerSheet("用户数据").build();

                int total = 1_000_000;
                int batchSize = 100_000;
                int batchCount = total / batchSize;

                for (int i = 0; i < batchCount; i++) {
                    List<User> batchData = generateBatchData(batchSize, i * batchSize);
                    excelWriter.write(batchData, writeSheet);
                    log.info("已生成第 {}/{} 批数据，共 {} 条", i + 1, batchCount, batchSize);
                }
            }

            long endTime = System.currentTimeMillis();
            log.info("百万数据Excel生成完成，文件路径: {}，耗时: {} 秒",
                    filePath, (endTime - startTime) / 1000.0);

            return filePath;

        } catch (Exception e) {
            log.error("生成Excel文件失败", e);
            throw new RuntimeException("生成Excel文件失败", e);
        }
    }

    /**
     * 生成测试数据（单次写入）
     */
    public String generateTestData(int recordCount) {
        String fileName = "test_data_" + recordCount + "_" + System.currentTimeMillis() + ".xlsx";
        String filePath = getFilePath(fileName);

        FileUtil.createFileDirectory(filePath);

        log.info("开始生成测试数据Excel文件: {}，记录数: {}", filePath, recordCount);

        try {
            List<User> data = generateBatchData(recordCount, 0);

            // 添加 LocalDate 转换器
            EasyExcel.write(filePath, User.class)
                    .registerConverter(new LocalDateConverter())
                    .sheet("测试数据")
                    .doWrite(data);

            log.info("测试数据Excel生成完成: {}", filePath);
            return filePath;

        } catch (Exception e) {
            log.error("生成测试Excel文件失败", e);
            throw new RuntimeException("生成测试Excel文件失败", e);
        }
    }

    /**
     * 使用自定义列宽策略
     */
    public String generateDataWithCustomWidth(int recordCount) {
        String fileName = "custom_width_data_" + recordCount + "_" + System.currentTimeMillis() + ".xlsx";
        String filePath = getFilePath(fileName);

        FileUtil.createFileDirectory(filePath);

        log.info("开始生成自定义列宽数据: {}，记录数: {}", filePath, recordCount);

        try {
            List<User> data = generateBatchData(recordCount, 0);

            // 使用自定义列宽策略
            EasyExcel.write(filePath, User.class)
                    .registerWriteHandler(new CustomColumnWidthStyleStrategy())
                    .sheet("用户数据")
                    .doWrite(data);

            log.info("自定义列宽数据生成完成: {}", filePath);
            return filePath;

        } catch (Exception e) {
            log.error("生成Excel文件失败", e);
            throw new RuntimeException("生成Excel文件失败", e);
        }
    }

    private List<User> generateBatchData(int size, int startIndex) {
        List<User> list = new ArrayList<>(size);
        Random random = new Random();

        for (int i = 0; i < size; i++) {
            User user = new User();
            user.setName(NAMES[random.nextInt(NAMES.length)] + (startIndex + i));
            user.setAge(20 + random.nextInt(40));
            user.setEmail("user" + (startIndex + i) + "@example.com");
            user.setDepartment(DEPARTMENTS[random.nextInt(DEPARTMENTS.length)]);
            user.setHireDate(String.valueOf(LocalDate.now().minusDays(random.nextInt(3650))));

            list.add(user);
        }
        return list;
    }

    private String getFilePath(String fileName) {
        return uploadDir + File.separator + fileName;
    }

    @PostConstruct
    public void init() {
        FileUtil.createDirectoryIfNotExists(uploadDir);
        log.info("文件上传目录已初始化: {}", uploadDir);
    }

    /**
     * 自定义列宽策略
     */
    public static class CustomColumnWidthStyleStrategy extends AbstractColumnWidthStyleStrategy {
        @Override
        protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<WriteCellData<?>> cellDataList,
                                      Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
            // 设置表头列宽
            if (isHead) {
                writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), 4000);
            } else {
                // 设置数据列宽
                writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), 6000);
            }
        }
    }
}
